package com.six.backend.ws;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.six.backend.dao.ToolDao;
import com.six.backend.pojo.Message;
import com.six.backend.pojo.Questionnaire;
import com.six.backend.service.ConferenceService;
import com.six.backend.utils.MessageUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: skyler
 * @Date: 2021/11/14 21:06
 */

@ServerEndpoint(value = "/chat/{roomName}",configurator = GetHttpSessionConfigurator.class)
@Component
public class ChatEndpoint {

    /**
     * 用来存储每一个客户端对象对应的ChatEndpoint对象
     */
    private static Map<String,Map<String,ChatEndpoint>> rooms = new ConcurrentHashMap<>();

    /**
     * 声明session对象，通过该对象可以发送消息给指定的用户
     */
    private Session session;

    /**
     * 声明一个HttpSession对象,我们之前在HttpSession对象中存储了用户名
     */
    private HttpSession httpSession;

    private static ConferenceService conferenceService;

    private static ToolDao toolDao;

    @Autowired
    public  void setApplicationContext(ConferenceService conferenceService,ToolDao toolDao) {
        ChatEndpoint.conferenceService= conferenceService;
        ChatEndpoint.toolDao = toolDao;
    }

    @OnOpen
    public void onOpen(@PathParam("roomName") String roomName, Session session, EndpointConfig config) {
        if (!rooms.containsKey(roomName)) {
            Map<String,ChatEndpoint> room = new HashMap<>();

            //将局部session赋值给成员session
            this.session = session;

            //获取httpSession对象
            HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
            this.httpSession = httpSession;

            //从httpSession对象中获取用户名

            String username = (String) httpSession.getAttribute("user");

            //把当前对象存储到map中
            room.put(username,this);

            //将当前对象存储到容器中
            rooms.put(roomName,room);

            //将当前在线用户的用户名推送给客户端
            //1.获取消息
            String message =  MessageUtils.getMessage(true,true,true,null,null,null,getNames(roomName));
            //将消息推送给用户
            broadcastAllUsers(roomName,message);
        } else {
            Map<String, ChatEndpoint> room = rooms.get(roomName);
            //将局部session赋值给成员session
            this.session = session;

            //获取httpSession对象
            HttpSession httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
            this.httpSession = httpSession;

            //从httpSession对象中获取用户名

            String username = (String) httpSession.getAttribute("user");

            //把当前对象存储到map中
            room.put(username,this);

            //将当前对象存储到容器中
            rooms.put(roomName,room);

            //将当前在线用户的用户名推送给客户端
            //1.获取消息
            String message =  MessageUtils.getMessage(true,true,true,null,null,null,getNames(roomName));
            //将消息推送给用户
            broadcastAllUsers(roomName,message);
        }
    }

    private void broadcastAllUsers(String roomName,String message) {
        try {
            Map<String,ChatEndpoint> room = rooms.get(roomName);

            Set<String> names = room.keySet();

            for (String name : names) {
                ChatEndpoint chatEndpoint = room.get(name);
                synchronized(chatEndpoint.session) {
                    chatEndpoint.session.getBasicRemote().sendText(message);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private Set<String> getNames(String roomName) {
        Map<String,ChatEndpoint> room = rooms.get(roomName);

        return room.keySet();
    }

    @OnMessage
    public void onMessage(@PathParam("roomName") String roomName,String message,Session session) {
        try {
            Map<String, ChatEndpoint> room = rooms.get(roomName);
            //将message对象转换成message对象
            ObjectMapper mapper = new ObjectMapper();
            Message message1 = mapper.readValue(message, Message.class);
            //获取消息数据
            String data = message1.getMessage();
            //获取当前登录的用户
            String username = (String) httpSession.getAttribute("user");
            //获取是否是推送消息
            boolean isPush = message1.isPush();
            //获取问卷id
            Integer delphiId = message1.getDelphiId();

            Integer questionnaireId;
            if (delphiId != null) {
                Questionnaire questionnaire = toolDao.selectQuestionnaireByDelphiId(delphiId);
                questionnaireId = questionnaire.getId();
            } else {
                questionnaireId = null;
            }
            //获取工具id
            Integer toolId = message1.getToolId();
            //是否是通知
            boolean isInform = message1.isInform();
            //持久化到数据库
            conferenceService.saveMessage(roomName,username,data,new Date());
            //心跳检测
            if ("ping!".equals(data)) {
                String resultMessage = MessageUtils.getMessage(isInform,isPush,false,username,null,null, "success");
                room.get(username).session.getBasicRemote().sendText(resultMessage);
            }else {
                //获取推送给指定用户的消息格式的数据
                String resultMessage = MessageUtils.getMessage(isInform,isPush,false,username,toolId,questionnaireId, data);
                //发送数据
                broadcastAllUsers(roomName,resultMessage);
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

    }
    @OnClose
    public void onClose(@PathParam("roomName") String roomName,Session session) {
        Map<String, ChatEndpoint> room = rooms.get(roomName);

        String username = (String) httpSession.getAttribute("user");

        room.remove(username);

        String message =  MessageUtils.getMessage(true,true,true,null,null,null,getNames(roomName));

        broadcastAllUsers(roomName,message);

    }

    @OnError
    public void onError(@PathParam("roomName") String roomName,Throwable throwable,Session session) {
        Map<String, ChatEndpoint> room = rooms.get(roomName);

        String username = (String) httpSession.getAttribute("user");

        room.remove(username);
    }


}
